﻿using System;
using System.Collections.Generic;
using System.Text;

namespace MiniGert
{
  /// <summary>
  /// Polygon is a simple polygonal closed line. When the line is drawn it start at the 
  /// first vertex in the list. From there the polygon is drawn as a line strip.
  /// The last and the first vertex are connected to close the polygon.
  /// </summary>
  public class Polygon
  {
    /// <summary>
    /// The internal field for the vertices.
    /// </summary>
    protected List<Point> _vertices = new List<Point>();

    /// <summary>
    /// Creates a new polygon with no vertices.
    /// </summary>
    public Polygon()
    {
    }

    /// <summary>
    /// Creates a new polygon with the given vertices.
    /// </summary>
    /// <param name="vertices">The vertices for the new polygon.</param>
    public Polygon(Point[] vertices)
    {
      _vertices.AddRange(vertices);
    }

    /// <summary>
    /// The list of vertices of the polygon.
    /// </summary>
    public List<Point> Vertices
    {
      get { return _vertices; }
      set { _vertices = value; }
    }

    /// <summary>
    /// Creates a rectanguar polygon with four vertices at the corners.
    /// </summary>
    /// <param name="width">The width of the rectangle.</param>
    /// <param name="height">The height of the rectangle.</param>
    /// <returns>The rectangle as a new polygon.</returns>
    public static Polygon Rectangle(float width, float height)
    {
      Polygon result = new Polygon();

      float halfWidth = width / 2;
      float halfHeight = height / 2;

      result.Vertices.Add(new Point(-halfWidth, halfHeight));
      result.Vertices.Add(new Point(halfWidth, halfHeight));
      result.Vertices.Add(new Point(halfWidth, -halfHeight));
      result.Vertices.Add(new Point(-halfWidth, -halfHeight));

      return result;
    }

    /// <summary>
    /// Creates a circular polygon with the given amount of vertices.
    /// </summary>
    /// <param name="radius">The raius of the circle.</param>
    /// <param name="vertices">The number of vertices to represent the circle.</param>
    /// <returns>The circle as a new polygon.</returns>
    public static Polygon Circle(float radius, int vertices)
    {
      Polygon result = new Polygon();

      double PI2 = (float)Math.PI * 2.0f;
      double angleStep = PI2 / vertices;
      for (double angle = 0.0f; angle < PI2; angle += angleStep)
      {
        result.Vertices.Add(new Point((float)Math.Sin(angle) * radius, (float)Math.Cos(angle) * radius));
      }

      return result;
    }

    /// <summary>
    /// Creates a polygon in the form of a star with the given amount of spikes. The polygon
    /// will has twice as many vertices as spikes.
    /// </summary>
    /// <param name="outerRadius">The radius of the outer points (spikes).</param>
    /// <param name="innerRadius">The radius of the inner points.</param>
    /// <param name="spikes">The number of spikes.</param>
    /// <returns>The start as a new Polygon.</returns>
    public static Polygon Star(float outerRadius, float innerRadius, int spikes)
    {
      Polygon result = new Polygon();

      double PI2 = (float)Math.PI * 2.0f;
      double angleStep = PI2 / (spikes * 2);
      bool isSpike = true;
      for (double angle = 0.0f; angle < PI2; angle += angleStep)
      {
        if (isSpike)
          result.Vertices.Add(new Point((float)Math.Sin(angle) * outerRadius, (float)Math.Cos(angle) * outerRadius));
        else
          result.Vertices.Add(new Point((float)Math.Sin(angle) * innerRadius, (float)Math.Cos(angle) * innerRadius));
        isSpike = !isSpike;
      }

      return result;
    }

  }
}
